package horoclient;

import javax.swing.*;

import java.util.Observer;
import java.util.Observable;
import java.awt.event.*;
import java.awt.*;
import client.*;

public class SwingGui extends JFrame implements Observer{
	private static final Font courier = new Font("Courier",Font.PLAIN,12);
	private static final long serialVersionUID = -958403258048298703L;
	
	private NetworkClient nc;
	private ClientGameState gs;
	private int internalPort = 49302;
	private static String header = "<html><font color=white><b>";
	private static String footer = "</b></font></html>";
	private final JLabel label = new JLabel(header + " Server IP " + footer);
	private final JButton J = new JButton("Connect");
	private volatile JFrame sr;
	
	public SwingGui(String server, int port, ClientGameState gs) {
		this.gs = gs;
		
		this.internalPort = port;
		setSize(200,200);
		setTitle("Client v2");
		
		ImagePanel ip = new ImagePanel(new ImageIcon( SwingGui.class.getResource("wave.JPG")).getImage());
		ip.setLayout(new BoxLayout(ip, BoxLayout.Y_AXIS));
		JPanel jp = new JPanel();
		JPanel panel = jp;
		ip.add(jp);
		
		
		panel.setBorder(BorderFactory.createEmptyBorder(40, 40, 40, 40));
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        
        
		final JTextField jta = new JTextField(server);
		
		//Swing hack!
        label.setFont(courier); 
        label.setFont(new Font("Georgia", Font.PLAIN, 14));
        label.setForeground(new Color(50, 50, 25));
		
		final Timer timer = new Timer(50,null);
		final JProgressBar jpb = new JProgressBar();
		ActionListener updateJPB = new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				int val = jpb.getValue();
				if (val >= 100) {
					J.setEnabled(true);
					timer.stop();
					if (connected()) {
						label.setText(header + "Connected" + footer);
						J.setText("Enter Lobby");
					} else {
						label.setText(header + "Failed" + footer);
						printFailure();
					}
					jpb.setValue(0);
				} else {
					J.setEnabled(false);
					String s = label.getText();
					int N = s.length()-header.length()-footer.length();
					s =  (N < 16 && s.length()>=N) ? s + ". " : "Loading ";
					label.setText(header + s + footer);
					jpb.setValue(val+1);
				}
			}
		};
		timer.addActionListener(updateJPB);
		
		J.addActionListener(new ActionListener() { 
			public void actionPerformed(ActionEvent e){
				if (J.getText().startsWith("C")) {
					String s = jta.getText();
					newServer(s,internalPort);
					connect();
					timer.start();
				} else {
					//System.err.println("Button Says Hi!");
					launchLobby();
				}
			}
		});
		
		
		
		jp.add(label);
		jp.add(Box.createRigidArea(new Dimension(0, 15)));
		jp.add(jta);
		jp.add(Box.createRigidArea(new Dimension(0, 15)));
		jp.add(jpb);
		jp.add(Box.createRigidArea(new Dimension(0, 15)));
		jp.add(J);
		jp.setOpaque(false);
		
		
		this.add(ip);
		this.pack();
		this.setResizable(false);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		newServer(server,port);

	}
	public void update (Observable a, Object b) {
		//Kill lobby window.
		if (nc.failed() && sr != null) {
			SwingUtilities.invokeLater(new Runnable(){public void run(){
				JOptionPane.showMessageDialog(null,"The Server Disconnected Unexpectedly");
				sr.dispose();
				disconnect();
			}});
			System.err.println("Network Thread Dies!");
		} else {
			//System.err.println("Network Thread Lives!");
		}
	}
	private void disconnect() {
		sr = null;
		System.err.println("Client Disconnecting");
		try { nc.close(); } catch (Exception e){}
		J.setText("Connect");
		label.setText(header + " Disconnected " + footer);
		gs.clear();
		this.validate();
		this.repaint();
	}
	
	private boolean newServer (String srvr, int port) {
		try { nc.close(); } catch (Exception e){}
		nc = null;
		try {nc = new NetworkClient(srvr,port); } catch (Exception e){e.printStackTrace();}
		if (nc == null) return false;
		nc.addObserver(gs);
		nc.addObserver(this);
		return true;
	}
	private void connect() {
		nc.start();
	}
	private boolean connected() {
		return nc.started();
	}
	private void printFailure() {
		if (nc.failed())
			nc.failure().printStackTrace();
	}
	// This launches the lobby window or refocuses 
	private void launchLobby() {
		if (sr != null) {
			sr.setExtendedState(NORMAL);
			sr.requestFocus();
		} else {
		final SwingLobby sL = new SwingLobby(nc,gs);
		SwingUtilities.invokeLater(new Runnable(){public void run(){sL.setVisible(true); sL.getAndSetPlayerName();}});
		sL.addWindowListener(new WindowListener(){

			public void windowActivated(WindowEvent e) {}
			public void windowClosed(WindowEvent e) { }
			public void windowClosing(WindowEvent e) { sr=null;disconnect();}
			public void windowDeactivated(WindowEvent e) {}
			public void windowDeiconified(WindowEvent e) {}
			public void windowIconified(WindowEvent e) {}
			public void windowOpened(WindowEvent e) {}
		});sr=sL;
		}
	}
	
	class ImagePanel extends JPanel {

		private static final long serialVersionUID = 7740225435573197143L;
		private Image img;

		  public ImagePanel(String img) {
		    this(new ImageIcon(img).getImage());
		  }

		  public ImagePanel(Image img) {
		    this.img = img;
		    Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));
		    setPreferredSize(size);
		    setMinimumSize(size);
		    setMaximumSize(size);
		    setSize(size);
		    setLayout(null);
		  }

		  public void paintComponent(Graphics g) {
		    g.drawImage(img, 0, 0, null);
		  }

		}
}
